#ifndef _MY_SERVICE_
#define _MY_SERVICE_
#include"data.hpp"
#include"httplib.h"
extern cloud::DataManager * data;
namespace cloud{
    class Service{
        private:
            int _server_port;
            std::string _server_ip;
            std::string _download_prefix;
            httplib::Server _server;
        private:
            static void Upload(const httplib::Request &req , httplib::Response &rsp){
                // post /upload 文件数据在正文中
                auto ret = req.has_file("file");//判断有没有文件上传的区域
                if(ret == false){
                    cout<<"not file upload\n";
                    rsp.status = 400;
                    return ;
                }
                const auto& file = req.get_file_value("file");
                // file.filename 文件名称  file.content 文件正文
                std::string back_dir = Config::GetInstance()->GetBackDir();//获取备份路径
                std::string realpath = back_dir + FileUtil(file.filename).FileName();
                FileUtil fu(realpath);
                fu.SetContent(file.content);//写入数据到文件
                BackupInfo info;
                info.NewBackupInfo(realpath);//创建备份信息
                data->Insert(info);//像管理数据添加备份信息
                return ;
            }//上传请求函数

            static std::string Timertostr(time_t T){
                std::string tmp = std::ctime(&T);
                return tmp;
            }
            static void ListShow(const httplib::Request &req , httplib::Response &rsp){
                //1.获取所有文件备份信息
                std::vector<BackupInfo> arry;
                data->GetAll(&arry);
                //2.根据所有备份信息，组织html文件数据
                std::stringstream ss;
                ss<<"<html><head><title>Download</title></head>";
                ss<<"<body><h1>Download</h1><table>";
                for(auto &a : arry){
                    ss<<"<tr>";
                    ss<<"<td><a href='"<<a.url<<"'>"<<FileUtil(a.real_path).FileName()<<"</a></td>";
                    ss<<"<td align= 'right'>"<<Timertostr(a.mtime)<<"</td>";
                    ss<<"<td align= 'right'>"<<a.fsize/1024<<"k</td>";
                    ss<<"</tr>";
                }
                ss<< "</table></body></html>";
                rsp.body = ss.str();
                rsp.set_header("Content-Type", "text/html");
                rsp.status=200;
                return;
            }//页面请求函数
            static std::string GetETage(const BackupInfo &info){
                //etg : filename-fsize-mtime
                FileUtil fu(info.real_path);
                std::string etag = fu.FileName();
                etag +="-";
                etag += std::to_string(info.fsize);
                etag +="-";
                etag += std::to_string(info.atime);//最后访问时间
                return etag;
            }
            static void Download(const httplib::Request &req , httplib::Response &rsp){
                //1.获取客户端请求的资源路劲path  req.path
                //2.根据资源路径，获取文件备份信息
                BackupInfo info;
                data->GetOneByURL(req.path , &info);
                //3.判断文件是否被压缩，如果被压缩，要先解压
                if(info.pack_flag == true){
                    FileUtil fu(info.pack_path);
                    fu.uncompress(info.real_path);
                    
                }
                //4.删除压缩包，修改备份信息
                //remove(info.pack_path.c_str());
                info.pack_flag = false;
                data->Update(info);
                
                bool retrans =false;
                std::string old_etag;
                if(req.has_header("If-Range")){
                    old_etag = req.get_header_value("If-Range");
                    if(old_etag == GetETage(info) ){//一致,符合断点续传
                        retrans = true;
                    }
                }
                //如果没有"If-Range"则是正常下载，或者有这个字段
                //但是字段值和当前文件的etag不一致，则也必须重新返回全部数据
                
                //6.设置响应头部字段：ETag, Accept-Ranges: bytes
                FileUtil fu(info.real_path );
                if(retrans == false){//正常下载
                std::cout<<"what?\n";
                fu.GetContent(&rsp.body);
                rsp.set_header("Accept_Ranges", "bytes");
                rsp.set_header("ETag" , GetETage(info));
                rsp.set_header("Content-Type" , "application/octet-stream");//请求为文件下载
                rsp.status = 200;
                }
                else{//断点续传 
                //httplib内部实现了断点续传请求
                //只需要我们将用户文件所有数据读取到rsp.body中，内部会自动
                //选择区间进行响应
                fu.GetContent(&rsp.body);
                rsp.set_header("Accept_Ranges", "bytes");
                rsp.set_header("ETag" , GetETage(info));
                rsp.set_header("Content-Type" , "application/octet-stream");//请求为文件下载
                rsp.status = 206;
                }
                
            }//下载请求函数
        public:
            Service(){
                Config *config = Config::GetInstance();
                _server_port = config->GetServerPort();
                _server_ip = config->GetServerIp();
                _download_prefix = config->GetDownloadPrefix();

            }
            bool RunMoudle(){
                std::cout<<"??\n";
                _server.Post("/upload" , Upload);
                _server.Get("/listshow" , ListShow);
                _server.Get("/" , ListShow);
                std::string download_url = _download_prefix +"(.*)";
                _server.Get(download_url ,Download);
                _server.listen(_server_ip.c_str() , _server_port);
                return true;
            } //服务器的搭建
    };
    


}


#endif